<?php
namespace app\index\model;

use app\index\model\pay\Pay;
use app\index\model\UrlUtil;
use think\Session;

require_once(dirname(__FILE__) . '/' . "../../extend/wxpay/lib/WxPay.Api.php");
require_once(dirname(__FILE__) . '/' . "../../extend/wxpay/lib/WxPay.Config.php");
require_once(dirname(__FILE__) . '/' . "../../extend/wxpay/lib/WxPay.Data.php");
require_once(dirname(__FILE__) . '/' . "../../extend/wxpay/lib/WxPay.Exception.php");

class Wxgzhpay extends Pay
{
    public $app_id = 'wx292e1491eca7a249';//appid和app_secret在开通微信支付后接收到的邮件里面可看到

    public $mch_id = '1493550662';//商户号

    public $makesign = '9JTOvroPhcxaAnosVXkwGtWlilsCkkOR';//支付的签名，32位签名，微信商户后台设置

    public $app_secret = '7dae8aa84a022ac8e160448f01523345';

    public $parameters;

    public $notify_url = 'http://www.mingtern.com';// 本控制器下面的 notifyurl  方法的URL路径 记得格式 是 http://......    【这是回调】

    public $error = 0;

    public $orderid = null;

    public $data = [];

    public function gzhpay()
    {
        $fee = 1;
        $no = '2018041300541882';
        $body = '公众号支付测试';
        $open_id = $this->GetOpenid();
        Session::set('openid', $open_id);
        $url = $this->payconfig($no, $fee, $body, $open_id);
        return $url;
    }
    #选择支付方式#
    #记得填写授权目录
    /**
     *
     * 获取jsapi支付的参数
     * @param array $UnifiedOrderResult 统一支付接口返回的数据
     * @throws WxPayException
     *
     * @return json数据，可直接填入js函数作为参数
     */
    public function GetJsApiParameters()
    {
        //①、获取用户openid
        $open_id = $this->GetOpenid();

        //②、统一下单
        $input = new \WxPayUnifiedOrder();
        $input->SetBody("test");
        $input->SetAttach("test");
        $input->SetOut_trade_no(\WxPayConfig::MCHID . date("YmdHis"));
        $input->SetTotal_fee("1");
        $input->SetTime_start(date("YmdHis"));
        $input->SetTime_expire(date("YmdHis", time() + 600));
        $input->SetGoods_tag("test");
        $input->SetNotify_url("http://paysdk.weixin.qq.com/example/notify.php");
        $input->SetTrade_type("JSAPI");
        $input->SetOpenid($open_id);
        $jsApiParameter = \WxPayApi::unifiedOrder($input);
        $jsApiParameters = $this->parmar($jsApiParameter);
        return $jsApiParameters;
    }

    public function parmar($UnifiedOrderResult)
    {
        if (!array_key_exists("appid", $UnifiedOrderResult)
            || !array_key_exists("prepay_id", $UnifiedOrderResult)
            || $UnifiedOrderResult['prepay_id'] == ""
        ) {
            throw new \WxPayException("参数错误");
        }
        $jsapi = new \WxPayJsApiPay();
        $jsapi->SetAppid($UnifiedOrderResult["appid"]);
        $timeStamp = time();
        $jsapi->SetTimeStamp("$timeStamp");
        $jsapi->SetNonceStr(\WxPayApi::getNonceStr());
        $jsapi->SetPackage("prepay_id=" . $UnifiedOrderResult['prepay_id']);
        $jsapi->SetSignType("MD5");
        $jsapi->SetPaySign($jsapi->MakeSign());
        $parameters = json_encode($jsapi->GetValues());
        return $parameters;
    }

    /**
     * 获取微信token
     * @author  曹旺
     * @data  10:19
     */
    public function access_token()
    {
        $paramsArr['grant_type'] = 'client_credential';
        $paramsArr['appid'] = 'wx292e1491eca7a249';
        $paramsArr['secret'] = '7dae8aa84a022ac8e160448f01523345';
        $url = 'https://api.weixin.qq.com/cgi-bin/token';
        $model = new UrlUtil();
        $access_token = $model->get($url, $paramsArr);
        dump(json_decode($access_token), true);

    }

    /**
     *
     * 通过跳转获取用户的openid，跳转流程如下：
     * 1、设置自己需要调回的url及其其他参数，跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize
     * 2、微信服务处理完成之后会跳转回用户redirect_uri地址，此时会带上一些参数，如：code
     *
     * @return 用户的openid
     */
    public function GetOpenid()
    {
        //$this->rizhi();
        //通过code获得openid
        if (!isset($_GET['code'])) {
            //return 1;
            //触发微信返回code码
            $baseUrl = urlencode('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . $_SERVER['QUERY_STRING']);
            //return $baseUrl;
            $url = $this->__CreateOauthUrlForCode($baseUrl);
            //return $url;
            Header("Location: $url");
            exit();
        } else {
            //return 2;
            //获取code码，以获取openid
            $code = $_GET['code'];
            //return $code;
            $openid = $this->getOpenidFromMp($code);
            return $openid;
        }
    }

    /**
     *
     * 构造获取code的url连接
     * @param string $redirectUrl 微信服务器回跳的url，需要url编码
     *
     * @return 返回构造好的url
     */
    public function __CreateOauthUrlForCode($redirectUrl)
    {
        $urlObj["appid"] = 'wx292e1491eca7a249';
        //return $urlObj["appid"];
        $urlObj["redirect_uri"] = "$redirectUrl";
        $urlObj["response_type"] = "code";
        $urlObj["scope"] = "snsapi_base";//snsapi_base
        $urlObj["state"] = "STATE" . "#wechat_redirect";
        $bizString = $this->ToUrlParams($urlObj);
        //return $bizString;
        return "https://open.weixin.qq.com/connect/oauth2/authorize?" . $bizString;
    }

    /**
     *
     * 通过code从工作平台获取openid机器access_token
     * @param string $code 微信跳转回来带上的code
     *
     * @return openid
     */
    public function GetOpenidFromMp($code)
    {
        //$path='http://www.importndsf.com/import_nbsm/nbsm_shopping/vendor/WxPayAPI_php_3/lib/WxPay.Config.php';
        //include($path);
        $url = $this->__CreateOauthUrlForOpenid($code);
        //初始化curl
        // return $url;
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //return WxPayConfig::CURL_PROXY_HOST;
        if (\WxPayConfig::CURL_PROXY_HOST != "0.0.0.0"
            && \WxPayConfig::CURL_PROXY_PORT != 0
        ) {
            //return 1;
            curl_setopt($ch, CURLOPT_PROXY, \WxPayConfig::CURL_PROXY_HOST);
            curl_setopt($ch, CURLOPT_PROXYPORT, \WxPayConfig::CURL_PROXY_PORT);
        }
        //return $ch;
        //运行curl，结果以jason形式返回
        $res = curl_exec($ch);
        curl_close($ch);
        //取出openid
        $data = json_decode($res, true);
        //return $res;
        $this->data = $data;
        $openid = $data['openid'];
        return $openid;
    }

    /**
     *
     * 构造获取open和access_toke的url地址
     * @param string $code ，微信跳转带回的code
     *
     * @return 请求的url
     */
    private function __CreateOauthUrlForOpenid($code)
    {
        //return 3;
        $urlObj["appid"] = \WxPayConfig::APPID;
        $urlObj["secret"] = \WxPayConfig::APPSECRET;
        $urlObj["code"] = $code;
        $urlObj["grant_type"] = "authorization_code";
        $bizString = $this->ToUrlParams($urlObj);
        return "https://api.weixin.qq.com/sns/oauth2/access_token?" . $bizString;
    }

    //回调
    public function actionNotifyurl()
    {
        $xml = file_get_contents("php://input");
        $log = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        $id = $log['out_trade_no'];  //获取单号

        //这里修改状态
        exit('SUCCESS');  //打死不能去掉
    }

    #微信JS支付参数获取#
    protected function payconfig($no, $fee, $body, $open_id)
    {
        //return $open_id;
        $openid = $open_id;
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        $data['appid'] = $this->app_id;
        //return $data['appid'];
        $data['mch_id'] = $this->mch_id; //商户号
        $data['device_info'] = 'WEB';
        $data['body'] = $body;
        $data['out_trade_no'] = $no; //订单号
        $data['total_fee'] = $fee; //金额
        $data['spbill_create_ip'] = $_SERVER["REMOTE_ADDR"];
        $data['notify_url'] = $this->notify_url;           //通知url
        $data['trade_type'] = 'JSAPI';
        $data['openid'] = $openid;   //获取openid
        $data['nonce_str'] = $this->createNoncestr();
        $data['sign'] = $this->MakeSign($data);
        //return json_encode($data);
        $xml = $this->ToXml($data);
        //return $data;

        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);

        //设置header
        curl_setopt($curl, CURLOPT_HEADER, FALSE);

        //要求结果为字符串且输出到屏幕上
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($curl, CURLOPT_POST, TRUE); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $xml); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
        $tmpInfo = curl_exec($curl); // 执行操作
        curl_close($curl); // 关闭CURL会话
        $arr = $this->FromXml($tmpInfo);
        return $arr;
    }

    /**
     *  作用：产生随机字符串，不长于32位
     */

    public function createNoncestr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }

        return $str;
    }

    /**
     *  作用：产生随机字符串，不长于32位
     */
    public function randomkeys($length)
    {
        $pattern = '1234567890123456789012345678905678901234';
        $key = null;

        for ($i = 0; $i < $length; $i++) {
            $key .= $pattern{mt_rand(0, 30)};    //生成php随机数
        }

        return $key;
    }

    /**
     * 将xml转为array
     * @param string $xml
     * @throws WxPayException
     */
    public function FromXml($xml)
    {
        //将XML转为array
        return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    }

    /**
     * 输出xml字符
     * @throws WxPayException
     **/
    public function ToXml($arr)
    {
        //return $arr;
        /*$artr['appid']='wx292e1491eca7a249';
        $artr['mch_id']='1493550662';
        $artr['device_info']='WEB';
        $artr['body']='公众号支付测试';
        $artr['out_trade_no']='2018041300541882';
        $artr['total_fee']='1';
        $artr['spbill_create_ip']='61.129.6.151';
        $artr['notify_url']='http://www.mingtern.com';
        $artr['trade_type']='JSAPI';
        $artr['openid']='oitD7v-ZiO7bE-XE6pMKf9HttLXs';
        $artr['nonce_str']='s5tjmh03eo7ffp60t3ph4at70l2cs2sx';
        $artr['sign']='53EE8F6F8BCDAC0B59BEC1048E169AB5';*/
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                //echo $val."-";die;
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
                //echo $xml;die;
            } else {
                //echo $val."+";die;
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
                //echo $xml;die;
            }
        }
        $xml .= "</xml>";
        return $xml;
    }

    /**
     * 生成签名
     * @return 签名，本函数不覆盖sign成员变量，如要设置签名需要调用SetSign方法赋值
     */
    protected function MakeSign($arr)
    {
        //签名步骤一：按字典序排序参数
        ksort($arr);
        $string = $this->ToUrlParams($arr);

        //签名步骤二：在string后加入KEY
        $string = $string . "&key=" . $this->makesign;

        //签名步骤三：MD5加密
        $string = md5($string);

        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);

        return $result;
    }

    /**
     * 格式化参数格式化成url参数
     */
    protected function ToUrlParams($arr)
    {
        $buff = "";

        foreach ($arr as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        return $buff;
    }
}

?>
